package cn.kduck.plugin.idea.utils;

import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static cn.kduck.plugin.idea.generate.CodeGenerator.VALUE_MAP_CLASS_NAME;

public class GeneratorUtils {

    private GeneratorUtils(){}

    /**
     * 获取字段的“//”形式的注释内容，如果字段没有“//”注释返回null
     */
    public static String getCommentForField(PsiField field) {
        if(field.getDocComment() != null){
            return null;
        }

        for (PsiElement child : field.getChildren()) {
            if (child instanceof PsiComment) {
                PsiComment comment = (PsiComment) child;
                String commentText = comment.getText();
                return commentText.trim().startsWith("//") ? commentText.replace("//","") : commentText;
            }
        }
        return null;
    }

    /**
     * 判断指定类是否为Kduck框架的ValueMap对象
     */
    public static boolean isValueMap(PsiClass javaClass){
        String className = javaClass.getQualifiedName();
        for(String valueMapClassName :VALUE_MAP_CLASS_NAME){
            if(valueMapClassName.equals(className)){
                return true;
            }
        }
        return false;
    }

    /**
     * 获取当前工程中是否有ValueMap的Class对象，如果没有则返回HashMap的Class对象
     */
    public static PsiClass getValueMapClass(Project project){
        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
        PsiClass extendClass = null;
        for(String className :VALUE_MAP_CLASS_NAME){
            extendClass = psiFacade.findClass(className, GlobalSearchScope.allScope(project));
            if(extendClass != null){
                break;
            }
        }
        if(extendClass == null){
            extendClass = psiFacade.findClass(HashMap.class.getName(), GlobalSearchScope.allScope(project));
        }
        return extendClass;
    }

    /**
     * 创建一个机遇vlauemap的setter方法
     */
    public static PsiMethod createSetterMethod(PsiElementFactory elementFactory, PsiField field, boolean isValueMap){
        return createSetterMethod(elementFactory,field,isValueMap,fieldName->StringUtils.upperCaseWithSeparator(fieldName, "_"));
    }

    /**
     * 创建一个机遇vlauemap的setter方法
     */
    public static PsiMethod createSetterMethod(PsiElementFactory elementFactory, PsiField field, boolean isValueMap,FieldNameFormatter formatter){
        PsiPrimitiveType voidType = elementFactory.createPrimitiveType("void");
        PsiMethod method = elementFactory.createMethod("set"+StringUtils.upperFirstChar(field.getName()), voidType);
        PsiParameter parameter = elementFactory.createParameter(field.getName(), field.getType());
        method.getParameterList().add(parameter);

        String fieldName = formatter.format(field.getName());
        String bodyText = "{super.put(" + fieldName + "," + parameter.getName() + ");}";
        PsiCodeBlock codeBlock = elementFactory.createCodeBlockFromText(bodyText, null);

        method.getBody().replace(codeBlock);

        return method;
    }


    /**
     * 创建一个基于valuemap的getter方法
     */
    public static PsiMethod createGetterMethod(PsiElementFactory elementFactory,PsiField field,boolean isValueMap){
        return createGetterMethod(elementFactory,field,isValueMap,fieldName->StringUtils.upperCaseWithSeparator(fieldName, "_"));
    }

    /**
     * 创建一个基于valuemap的getter方法
     */
    public static PsiMethod createGetterMethod(PsiElementFactory elementFactory,PsiField field,boolean isValueMap,FieldNameFormatter formatter){
        PsiType type = field.getType();
        PsiMethod method = elementFactory.createMethod("get"+StringUtils.upperFirstChar(field.getName()), type);

        String bodyText;

        boolean  isUnsupportedType = true;
        String methodName = null;
        String canonicalText = type.getCanonicalText();
        if(String.class.getName().equals(canonicalText)
                || Integer.class.getName().equals(canonicalText)
                || Date.class.getName().equals(canonicalText)
                || Long.class.getName().equals(canonicalText)
                || Double.class.getName().equals(canonicalText)
                || Boolean.class.getName().equals(canonicalText)){
            methodName = type.getPresentableText();
        }else if(isValueMap && type instanceof PsiPrimitiveType){
            methodName = type.getPresentableText();
            if(type.getPresentableText().equals("boolean")){
                methodName = "bool";
            }
        }else{
            isUnsupportedType = false;
            methodName = type.getPresentableText();
        }
//        else if (type instanceof PsiArrayType) {
//            PsiArrayType psiArrayType = (PsiArrayType) type;
//            result = "super.getValueAsArray(" + keyName + "," + psiArrayType.getComponentType().getPresentableText() + ".class);";
//        }
        String fieldName = formatter.format(field.getName());
        if(isValueMap){
            //处理ValueMap的get及set方法
            if(!isUnsupportedType){
                bodyText = "{return ("+StringUtils.upperFirstChar(methodName)+") super.get("+fieldName+");}";
            }else{
                bodyText = "{return super.getValueAs" + StringUtils.upperFirstChar(methodName) + "("+fieldName+");}";
            }

        }else{
            //处理HashMap的get及set方法
            if(type instanceof PsiPrimitiveType){
                String warpperType;
                String defaultValue;
                String typeText = type.getPresentableText();
                if("int".equals(typeText)){
                    warpperType = "Integer";
                    defaultValue = "0";
                }else if("long".equals(typeText)){
                    warpperType = "Long";
                    defaultValue = "0L";
                }else if("float".equals(typeText)){
                    warpperType = "Float";
                    defaultValue = "0F";
                }else if("double".equals(typeText)){
                    warpperType = "Double";
                    defaultValue = "0D";
                }else if("boolean".equals(typeText)){
                    warpperType = "Boolean";
                    defaultValue = "false";
                }else{
                    warpperType = "Object";
                    defaultValue = "null";
                }
                bodyText = "{Object value = super.get("+fieldName+");if(value != null){return (" + warpperType + ")value;}return " + defaultValue + ";}";
            } else {
                bodyText = "{return ("+StringUtils.upperFirstChar(methodName)+") super.get("+fieldName+");}";
            }
        }
        PsiCodeBlock codeBlock = elementFactory.createCodeBlockFromText(bodyText, null);

        method.getBody().replace(codeBlock);

        return method;
    }


    /**
     * 添加继承类，如果存在则替换
     */
    public static void addExtendClass(PsiElementFactory elementFactory,PsiClass sourceClass,PsiClass extendClass) {
        PsiReferenceList extendsList = sourceClass.getExtendsList();
        PsiJavaCodeReferenceElement extendReference = elementFactory
                .createClassReferenceElement(extendClass);
        PsiJavaCodeReferenceElement[] referenceElements = extendsList.getReferenceElements();
        if(referenceElements.length > 0){
            referenceElements[0].replace(extendReference);
        }else{
            extendsList.add(extendReference);
        }
    }

    /**
     * 创建一个默认构造器和一个带有map参数的构造器
     */
    public static void createConstructor(PsiElementFactory elementFactory,Project project, PsiClass javaClass) {
        //判断默认构造器和map参数构造器是否已经存在，避免重复创建
        PsiMethod[] constructors = javaClass.getConstructors();
        boolean hasDefaultConstructor = false;
        boolean hasMapConstructor = false;
        if(constructors.length > 0){
            for (PsiMethod constructor : constructors) {
                PsiParameterList parameterList = constructor.getParameterList();
                if(parameterList.isEmpty()){
                    hasDefaultConstructor = true;
                }else if(parameterList.getParametersCount() == 1){
                    PsiType type = parameterList.getParameter(0).getType();
                    String paramName = type.getCanonicalText();
                    if(Map.class.getName().equals(paramName) || HashMap.class.getName().equals(paramName)){
                        hasMapConstructor = true;
                    }
                }
            }
        }

        if(!hasDefaultConstructor){
            javaClass.add(elementFactory.createConstructor());//增加空构造器
        }

        if(!hasMapConstructor){
            PsiClassType mapType = PsiClassType.getTypeByName(Map.class.getName(), project, GlobalSearchScope.allScope(project));
            PsiMethod mapConstructor = elementFactory.createConstructor();
            mapConstructor.getParameterList().add(elementFactory.createParameter("map",mapType));
            String constructorCode = "{if(map != null){super.putAll(map);}}";
            PsiCodeBlock codeBlock = elementFactory.createCodeBlockFromText(constructorCode, null);
            mapConstructor.getBody().replace(codeBlock);
            javaClass.add(mapConstructor);//增加map参数构造器
        }

    }

    public interface FieldNameFormatter{
        String format(String fieldName);
    }
}
